package com.jumper.property.comparer.starter;


import com.jumper.property.comparer.core.annotations.UniqueKey;
import com.jumper.property.comparer.core.enums.LogTable;
import com.jumper.property.comparer.starter.exception.LoggerException;
import com.jumper.property.comparer.core.support.AbstractBatchLogManager;
import com.jumper.property.comparer.core.support.AbstractLogManager;
import com.jumper.property.comparer.core.support.LogRepository;

import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

/**
 * 日志配置
 */
public final class LoggerConfiguration implements LoggerManager {

    private final static Map<LogTable, AbstractLogManager<?>> LOGGER_INFO = new ConcurrentHashMap<>();
    private final static Map<LogTable, AbstractBatchLogManager<?, ?>> MULTI_LOGGER_INFO = new ConcurrentHashMap<>();

    @Override
    public <T> AbstractLogManager<T> getLogger(LogTable type) {
        return (AbstractLogManager<T>) LOGGER_INFO.get(type);
    }

    @Override
    public <T> AbstractLogManager<T> loadLogger(LogTable type) {
        AbstractLogManager<T> logger = getLogger(type);
        if (Objects.isNull(logger)) {
            throw new LoggerException("[" + type + "]Logger未找到");
        }
        return logger;
    }

    @Override
    public <K extends UniqueKey<T>, T> AbstractBatchLogManager<K, T> getMultiLogger(LogTable type) {
        return (AbstractBatchLogManager<K, T>) MULTI_LOGGER_INFO.get(type);
    }

    @Override
    public <K extends UniqueKey<T>, T> AbstractBatchLogManager<K, T> loadMultiLogger(LogTable type) {
        AbstractBatchLogManager<K, T> logger = getMultiLogger(type);
        if (Objects.isNull(logger)) {
            throw new LoggerException("[" + type + "]Logger未找到");
        }
        return logger;
    }

    @Override
    public <T> void registerLogger(LogTable type, Function<T, Object> getOneFunc, LogRepository repository) {
        AbstractLogManager<T> manager = new AbstractLogManager<T>(repository) {
            @Override
            public LogTable getBusType() {
                return type;
            }

            @Override
            public Object getOptData(T optDataKey) {
                return getOneFunc.apply(optDataKey);
            }
        };
        put(type, manager);
    }

    @Override
    public <T> void registerLogger(LogTable type, AbstractLogManager<T> manager) {
        put(type, manager);
    }


    @Override
    public <K extends UniqueKey<T>, T> void registerMultiLogger(LogTable type, Function<Collection<T>, Set<K>> getListFunc, LogRepository repository) {
        AbstractBatchLogManager<K, T> manager = new AbstractBatchLogManager<K, T>(repository) {

            @Override
            public LogTable getBusType() {
                return type;
            }

            @Override
            public Set<K> getOptDataList(Collection<T> optDataKeys) {
                return getListFunc.apply(optDataKeys);
            }
        };
        put(type, manager);
    }

    @Override
    public <K extends UniqueKey<T>, T> void registerMultiLogger(LogTable type, AbstractBatchLogManager<K, T> manager) {
        put(type, manager);
    }

    /**
     * 注册单数据处理Manager
     */
    private <T> void put(LogTable type, AbstractLogManager<T> manager) {
        if (Objects.isNull(type)) {
            throw new LoggerException("Logger注册类型不能为空");
        }
        AbstractLogManager<?> putRet = LOGGER_INFO.putIfAbsent(type, manager);
        if (Objects.nonNull(putRet)) {
            throw new LoggerException("[" + type.getLogTableDesc() + "]Logger已存在,轻勿重新注册");
        }
    }

    /**
     * 注册单数据处理Manager
     */
    private <K extends UniqueKey<T>, T> void put(LogTable type, AbstractBatchLogManager<K, T> manager) {
        if (Objects.isNull(type)) {
            throw new LoggerException("Logger注册类型不能为空");
        }
        AbstractLogManager<?> putRet = MULTI_LOGGER_INFO.putIfAbsent(type, manager);
        if (Objects.nonNull(putRet)) {
            throw new LoggerException("[" + type.getLogTableDesc() + "]Logger已存在,轻勿重新注册");
        }
    }


}
